package cn.com.surker.weight.controller;

import cn.com.surker.base.system.entity.SysStorage;
import cn.com.surker.base.system.service.SysStorageService;
import cn.com.surker.common.AbstractController;
import cn.com.surker.common.Code;
import cn.com.surker.spring.RestResultDto;
import cn.com.surker.system.entity.DataSourceInfo;
import cn.com.surker.system.model.CacheUser;
import cn.com.surker.thread.ThreadPools;
import cn.com.surker.util.DateUtil;
import cn.com.surker.util.StringUtils;
import cn.com.surker.wechat.WechatSurkerGroupApi;
import cn.com.surker.weight.dao.WeightExamineMessageDao;
import cn.com.surker.weight.entity.WeightExamineMessage;
import cn.com.surker.weight.entity.WeightOrder;
import cn.com.surker.weight.entity.WeightSpotCheck;
import cn.com.surker.weight.service.ErpMainMaterialInspectionService;
import cn.com.surker.weight.service.ErpWeightOrderService;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.transaction.RollbackException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author luotao
 * @date 2024/11/16
 */
@RequestMapping("/weight/order")
@RestController
public class OrderController extends AbstractController {

	@Resource
	private ErpMainMaterialInspectionService weightCheckService;

	@Resource
	private ErpWeightOrderService weightOrderService;

	@Resource
	private SysStorageService sysStorageService;

	@Resource
	private WeightExamineMessageDao weightExamineMessageDao;

	/**
	 * 根据材料id查询对应的仓位
	 *
	 * @param materialId
	 * @return
	 */
	@RequestMapping(value = "/storage", method = RequestMethod.POST)
	@ResponseBody
	public RestResultDto material(Long materialId) {
		if (orgId == null || materialId == null) {
			return RestResultDto.fail(Code.PARAM_EMPTY);
		}
		List<SysStorage> storages = sysStorageService.findByMaterial(materialId);
		return RestResultDto.success(storages);
	}

	/**
	 * 待检订单列表
	 *
	 * @return
	 */
	@RequestMapping(value = "/wait/list", method = RequestMethod.POST)
	@ResponseBody
	public RestResultDto waitList() {
		List<WeightOrder> list = weightOrderService.waitList();
		return RestResultDto.success(list);
	}

	/**
	 * 待检订单详情
	 *
	 * @param code
	 * @return
	 */
	@RequestMapping(value = "/wait/detail/{code}", method = RequestMethod.POST)
	@ResponseBody
	public RestResultDto waitDetail(@PathVariable String code) {
		if (code == null) {
			return RestResultDto.fail(Code.PARAM_EMPTY);
		}
		WeightOrder orderData = weightOrderService.queryByCode(code);
		if (orderData != null) {
			//	如果是地材,则需要验证是否需要抽检,查询是否有抽检数据
			boolean needCheck = false;
			//	使用0,1用验证有助于前端判断,0,不需要抽检,1,需要抽检
			Integer spotCheck = 0;
			try {
				Integer ps = orderData.getStorageType();
				if (ps == 1) {
					//	仓位为1,表示地材
					needCheck = true;
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			/*if (needCheck) {
				//	查询数据库,该订单是否需要检测
				Boolean nc = weightCheckService.needCheck( code);
				if(nc){
					spotCheck = 1;
				}
			}*/
			// orderData.put("spotCheck", spotCheck);
			orderData.setSpotCheck(spotCheck);
			return RestResultDto.success(orderData);
		}
		return RestResultDto.fail(Code.NO_DATA);
	}

	/**
	 * 订单详情
	 *
	 * @param code
	 * @return
	 */
	@RequestMapping(value = "/detail/{code}", method = RequestMethod.POST)
	@ResponseBody
	public RestResultDto orderDetail(@PathVariable String code) {
		if (StringUtils.isBlank(code)) {
			return RestResultDto.fail(Code.PARAM_EMPTY);
		}
		WeightOrder orderData = weightOrderService.queryByCode(code);
		if (orderData != null) {
			return RestResultDto.success(orderData);
		}
		return RestResultDto.fail(Code.NO_DATA);
	}

	/**
	 * 审核数据
	 *
	 * @param code        订单code
	 * @param checkStatus 审核状态,1通过,2拒绝
	 * @param position    仓位位置
	 * @param minusWeight 扣重数据
	 * @param remarks
	 * @return
	 */
	@RequestMapping(value = "/examine/{code}", method = RequestMethod.PUT)
	@ResponseBody
	@Transactional(rollbackFor = RollbackException.class, propagation = Propagation.REQUIRED)
	public RestResultDto examine(@PathVariable String code, Integer checkStatus, String position, String positionName, Double minusWeight, Integer spotCheck, String remarks) {
		if (code == null || checkStatus == null) {
			return RestResultDto.fail(Code.PARAM_EMPTY);
		}
		CacheUser user = getUser();
		Long originId = user.getOriginId();
		String userName = user.getName();
		// 查询本地数据
		WeightOrder localData = weightOrderService.queryByCode(code);
		if (localData == null) {
			return RestResultDto.fail(Code.NO_DATA);
		}
		Integer orderCS = localData.getCheckStatus();
		if (orderCS != null) {
			if (orderCS.equals(1) || orderCS.equals(2)) {
				//	1为通过,2为拒绝
				return RestResultDto.fail("该数据已经审核过");
			}
		}
		// 微信码
		String wxCode = localData.getOpenid();
		String driverName = localData.getDriver();
		String uCode = localData.getCode();
		//	车牌号
		String busNumber = localData.getBusNumber();
		if (checkStatus.equals(1)) {
			// 通过
			if (spotCheck != null && spotCheck.equals(1)) {
				// 	需要抽检,修改过磅数据
				Integer adopt = weightOrderService.spotCheck(code, wxCode, driverName);
				if (adopt > 0) {
					return RestResultDto.success("设置车辆抽检成功");
				} else {
					return RestResultDto.fail("保存失败");
				}
			} else {
				//	不需要抽检或者抽检通过
				if (StringUtils.isBlank(position)) {
					// 要选择仓位
					return RestResultDto.fail(Code.PARAM_EMPTY);
				}
				// 修改抽检记录
				updateSpotData(localData, originId, WeightSpotCheck.CHECKSTATUS_ADOPT, code, user.getName(), remarks);
				//	修改过磅数据
				Integer adopt = weightOrderService.adopt(code, userName, position, positionName, minusWeight, wxCode, driverName);
				if (adopt > 0) {
					writeOffWechatCardMsg(uCode, checkStatus, "已通过");
					return RestResultDto.success();
				} else {
					return RestResultDto.fail("保存失败");
				}
			}
		}
		if (checkStatus.equals(2)) {
			// 修改抽检记录
			updateSpotData(localData, originId, WeightSpotCheck.CHECKSTATUS_REFUSE, code, user.getName(), remarks);
			//	拒绝
			Integer refuse = weightOrderService.refuse(code, userName, remarks, wxCode, driverName);
			if (refuse > 0) {
				// 删除云端数据
				//	Integer r2 = weightOrderService.deleteByCode(code);
				writeOffWechatCardMsg(uCode, checkStatus, "已拒绝");
				return RestResultDto.success();
			} else {
				return RestResultDto.fail("保存失败");
			}
		}
		return RestResultDto.success();
	}

	/**
	 * 二次过磅列表
	 *
	 * @param offset
	 * @param limit
	 * @return
	 */
	@RequestMapping(value = "/again/list", method = RequestMethod.POST)
	@ResponseBody
	public RestResultDto againList(Integer offset, Integer limit) {
		CacheUser user = getUser();
		DataSourceInfo ds = user.getDataSourceInfo();
		List<WeightOrder> list = weightOrderService.againList();
		return RestResultDto.success(list);
	}

	@RequestMapping(value = "/again/adopt/{code}", method = RequestMethod.PUT)
	@ResponseBody
	public RestResultDto againAdopt(@PathVariable String code) {
		CacheUser user = getUser();
		DataSourceInfo ds = user.getDataSourceInfo();
		Integer adopt = weightOrderService.adoptAgain(code);
		if (adopt > 0) {
			return RestResultDto.success();
		} else {
			return RestResultDto.fail("保存失败");
		}
	}

	/**
	 * 全部数据列表
	 *
	 * @param searchVal 搜索数据
	 * @param offset    分页信息
	 * @param limit
	 * @return
	 */
	@RequestMapping(value = "/all/page", method = RequestMethod.POST)
	@ResponseBody
	public RestResultDto page(String searchVal, Integer examineStatus, String startTime, String endTime, Integer offset, Integer limit) {
		Date sTime = null, eTime = null;
		if (StringUtils.isNotBlank(startTime)) {
			try {
				sTime = DateUtil.convertDate(startTime, "yyyy-MM-dd HH:mm");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (StringUtils.isNotBlank(endTime)) {
			try {
				eTime = DateUtil.convertDate(endTime, "yyyy-MM-dd HH:mm");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (offset == null) {
			offset = 0;
		}
		if (limit == null) {
			limit = 15;
		}
		IPage<WeightOrder> page = weightOrderService.findPage(searchVal, examineStatus, sTime, eTime, offset, limit);
		return RestResultDto.success(page);
	}

	@RequestMapping(value = "/detail/{id}", method = RequestMethod.POST)
	@ResponseBody
	public RestResultDto detail(@PathVariable Long id) {
		if (id == null) {
			return RestResultDto.fail(Code.PARAM_EMPTY);
		}
		WeightOrder data = weightOrderService.getById(id);
		return RestResultDto.success(data);
	}

	/**
	 * 删除数据
	 *
	 * @param id
	 * @return
	 */
	@RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE)
	@ResponseBody
	@Transactional(rollbackFor = RollbackException.class, propagation = Propagation.REQUIRED)
	public RestResultDto delete(@PathVariable Long id) {
		if (id == null) {
			return RestResultDto.fail(Code.PARAM_EMPTY);
		}
		WeightOrder order = weightOrderService.getById(id);
		if (order == null) {
			return RestResultDto.fail(Code.NO_DATA);
		}
		String code = order.getCode();
		Long dsId = order.getStationId();
		if (StringUtils.isBlank(code) || dsId == null) {
			// 	没有订单号
			return RestResultDto.fail(Code.OA_BIZID_EMPTY);
		}
		// s删除本地数据
		Integer d2 = weightOrderService.deleteByCode(code);
		return RestResultDto.success();
	}

	/**
	 * 抽检订单列表
	 *
	 * @return
	 */
	@RequestMapping(value = "/check/list", method = RequestMethod.POST)
	@ResponseBody
	public RestResultDto checkList() {
		List<WeightOrder> list = weightOrderService.checkList();
		return RestResultDto.success(list);
	}

	/**
	 * 分仓列表
	 *
	 * @param offset
	 * @param limit
	 * @return
	 */
	@RequestMapping(value = "/unskinned/page", method = RequestMethod.POST)
	@ResponseBody
	public RestResultDto compList(Integer offset, Integer limit) {
		IPage<WeightOrder> list = weightOrderService.unskinnedList(offset, limit);
		return RestResultDto.success(list);
	}

	/**
	 * 运行分仓
	 *
	 * @param code
	 * @return
	 */
	@RequestMapping(value = "/unskinned/do/{code}", method = RequestMethod.PUT)
	@ResponseBody
	@Transactional(rollbackFor = RollbackException.class, propagation = Propagation.REQUIRED)
	public RestResultDto compDo(@PathVariable String code) {
		if (StringUtils.isBlank(code)) {
			return RestResultDto.fail(Code.PARAM_EMPTY);
		}
		Boolean b = weightOrderService.compDo(code);
		if (b) {
			return RestResultDto.success();
		} else {
			return RestResultDto.fail();
		}
	}

	/**
	 * 已经过重磅的数据列表
	 *
	 * @param searchVal 搜索数据
	 * @param offset    分页信息
	 * @param limit
	 * @return
	 */
	@RequestMapping(value = "/gross/page", method = RequestMethod.POST)
	@ResponseBody
	public RestResultDto grossPage(String searchVal, Integer examineStatus,
								   String startTime, String endTime, Integer offset, Integer limit) {
		Date sTime = null, eTime = null;
		if (StringUtils.isNotBlank(startTime)) {
			try {
				sTime = DateUtil.convertDate(startTime, "yyyy-MM-dd HH:mm");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (StringUtils.isNotBlank(endTime)) {
			try {
				eTime = DateUtil.convertDate(endTime, "yyyy-MM-dd HH:mm");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		IPage<WeightOrder> page = weightOrderService.grossPage(searchVal, examineStatus, sTime, eTime, offset, limit);
		return RestResultDto.success(page);
	}

	@RequestMapping(value = "/update/silo/{code}", method = RequestMethod.PUT)
	@ResponseBody
	@Transactional(rollbackFor = RollbackException.class, propagation = Propagation.REQUIRED)
	public RestResultDto updateSilo(@PathVariable String code, String position, String positionName, String remarks) {
		if (code == null) {
			return RestResultDto.fail(Code.PARAM_EMPTY);
		}
		// 查询本地数据
		WeightOrder localData = weightOrderService.queryByCode(code);
		if (localData == null) {
			return RestResultDto.fail(Code.NO_DATA);
		}
		//	设置仓位
		weightOrderService.updatePosition(code, position, positionName);
		return RestResultDto.success();
	}


	@RequestMapping(value = "/update/creTime", method = RequestMethod.PUT)
	@ResponseBody
	@Transactional(rollbackFor = RollbackException.class, propagation = Propagation.REQUIRED)
	public RestResultDto updateTime(String orderCode, String cTime) {
		if (StringUtils.isBlank(orderCode) || !StringUtils.validatorDate(cTime, DateUtil.DATE_DETAIL_FORMATTER)) {
			return RestResultDto.fail(Code.PARAM_EMPTY);
		}
		// 查询本地数据
		WeightOrder localData = weightOrderService.queryByCode(orderCode);
		if (localData == null) {
			return RestResultDto.fail(Code.NO_DATA);
		}
		//	更新时间
		weightOrderService.updateCreTime(orderCode, cTime);
		return RestResultDto.success();
	}

	/**
	 * 发送微信回调信息
	 *
	 * @param orderCode
	 */
	public void writeOffWechatCardMsg(String orderCode, Integer examineType, String examineText) {
		if (StringUtils.isBlank(orderCode)) {
			return;
		}
		// 发送审核过的消息
		ThreadPoolExecutor commonThreadPool = ThreadPools.getCommonThreadPool();
		commonThreadPool.execute(new Runnable() {
			@Override
			public void run() {
				// 查询数据
				List<WeightExamineMessage> weightMesgs = weightExamineMessageDao.findByOrderId(0, orderCode);
				if (weightMesgs != null && weightMesgs.size() > 0) {
					// 存在未核销数据
					List<String> rCodes = new ArrayList<>();
					for (int i = 0, s = weightMesgs.size(); i < s; i++) {
						WeightExamineMessage weightExamineMessage = weightMesgs.get(i);
						String toAccount = weightExamineMessage.getToAccount();
						String code = weightExamineMessage.getCode();
						if (StringUtils.isBlank(code) || StringUtils.isBlank(toAccount)) {
							// 没有查到微信code码
							continue;
						}
						JSONArray userIds = new JSONArray();
						userIds.add(toAccount);
						// 核销微信数据
						Boolean aBoolean = WechatSurkerGroupApi.updateCardMessage(WechatSurkerGroupApi.corpID, WechatSurkerGroupApi.corpSecret, WechatSurkerGroupApi.agentId, userIds, code, examineText);
						if (aBoolean) {
							rCodes.add(code);
						}
					}
					// 执行完微信的核销数据后,更改数据
					UpdateWrapper<WeightExamineMessage> uw = new UpdateWrapper<>();
					uw.set("is_callback", 1);
					uw.set("examine_type", examineType);
					uw.in("code", rCodes);
					weightExamineMessageDao.update(new WeightExamineMessage(), uw);
				}
			}
		});
	}

	private void updateSpotData(WeightOrder localData, Long originId, Integer checkStatus, String code, String userName, String remarks) {
		weightCheckService.updateCheck(localData, originId, code, checkStatus, userName, remarks);
	}
}
